﻿// ....................................................................................................................
//	Author: Copyright (C) 2012 Ing. Marek Hubal
//	Email: hubal@acasoftware.org
// ....................................................................................................................

using System;

namespace core
{
    /// <summary>Trieda ICRC32</summary>
	public class ICRC32 : IDisposable
	{
        uint[] FTable; 
        protected uint FValue;

        /// <summary>Property: Value</summary>
        public uint Value
        {
            get
            {
                return FValue;
            }
        }
        /// <summary>Property: HEXValue</summary>
        public string HEXValue
        {
            get
            {
                return Value.ToString("X8");
            }
        }

        /// <summary>Konstruktor</summary>
        public ICRC32()
        {
            FTable = new uint[256]; // Inicializacia
        }
        /// <summary>Dispose metoda</summary>
        public void Dispose()
        {
        }

        /// <summary>Inicializacia</summary>
        public void Init()
        {
            FValue = 0xffffffff;
            uint U = 0xedb88320;
            uint temp = 0;

            for (uint i = 0; i < FTable.Length; ++i) // Inicializacia tabulky
            {
                temp = i;
                for (int j = 8; j > 0; --j)
                {
                    if ((temp & 1) == 1)
                    {
                        temp = (uint)((temp >> 1) ^ U);
                    }
                    else
                    {
                        temp >>= 1;
                    }
                }
                FTable[i] = temp;
            }
        }
        /// <summary>Ukoncenie vypoctu</summary>
        public void Finish()
        {
            FValue = ~FValue;
        }

        /// <summary>Zaradenie dat do vypoctu</summary>
        /// <param name="pData">data</param>
        /// <param name="pStart">zaciatok</param>
        /// <param name="pLength">dlzka</param>
        public void AddDataBlock(byte[] pData, int pStart, int pLength)
        {
            for (int i = pStart; i < pLength; i++)
            {
                byte index = (byte)(((FValue) & 0xff) ^ pData[i]);
                FValue = (uint)((FValue >> 8) ^ FTable[index]);
            }
        }
        /// <summary>Zaradenie dat do vypoctu</summary>
        /// <param name="pData">data</param>
        /// <param name="pStart">zaciatok</param>
        /// <param name="pLength">dlzka</param>
        public void AddDataBlock(IntPtr pData, int pStart, int pLength)
        {
            for (int i = pStart; i < pLength; i++)
            {
                byte B = System.Runtime.InteropServices.Marshal.ReadByte(pData, i); // Ziskam byte
                byte index = (byte)(((FValue) & 0xff) ^ B);
                FValue = (uint)((FValue >> 8) ^ FTable[index]);
            }
        }
    }

    /// <summary>Trieda IEncryptor</summary>
    public class IEncryptor : IDisposable
    {
        public const int ENCRYPTION_TYPE_AES128 = 0;
        public const int ENCRYPTION_TYPE_AES192 = 1;
        public const int ENCRYPTION_TYPE_AES256 = 2;
        public const int ENCRYPTION_TYPE_DES = 3;
        public const int ENCRYPTION_TYPE_RC2_64 = 4;
        public const int ENCRYPTION_TYPE_RC2_128 = 5;
        public const int ENCRYPTION_TYPE_TRIPLE_DES_128 = 6;
        public const int ENCRYPTION_TYPE_TRIPLE_DES_192 = 7;

        protected byte FType;
        protected System.Security.Cryptography.PasswordDeriveBytes FPassword; // Heslo
        public long OriginalSize;
        public string OriginalName;

        /// <summary>Konstruktor</summary>
        public IEncryptor()
        {
            FPassword = null;
            OriginalSize = -1; OriginalName = "";
            FType = 0;
        }
        /// <summary>Dispose metoda</summary>
        public virtual void Dispose()
        {
            FPassword = (System.Security.Cryptography.PasswordDeriveBytes)ICore.DisposeObject(FPassword);
        }

        /// <summary>Priprava hesla</summary>
        /// <param name="pValue">heslo</param>
        protected void PreparePassword(string pValue)
        {
            FPassword = new System.Security.Cryptography.PasswordDeriveBytes(pValue, new byte[] {0x22, 0x31, 0x45, 0x51, 0x64, 0x7a, 0x87, 0x96, 0xa0, 0xbb, 0xce, 0xd8, 0xe5});
        }
        /// <summary>Priprava hesla</summary>
        /// <param name="pValue">heslo</param>
        protected void PreparePassword(byte[] pValue)
        {
            try
            {
                FPassword = new System.Security.Cryptography.PasswordDeriveBytes(System.Convert.ToBase64String(pValue), new byte[] { 0x22, 0x31, 0x45, 0x51, 0x64, 0x7a, 0x87, 0x96, 0xa0, 0xbb, 0xce, 0xd8, 0xe5 });
            }
            catch
            {
            }
        }

        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public virtual void Init(string pPassword, System.IO.Stream pStream)
        {
            PreparePassword(pPassword); // Pripravim heslo
            try
            {
                pStream.WriteByte((byte)'t'); // Signatura
                pStream.WriteByte((byte)'l');
                pStream.WriteByte((byte)'m');
                pStream.WriteByte((byte)'e');
                pStream.WriteByte((byte)'n');
                pStream.WriteByte((byte)'c');
                pStream.WriteByte((byte)'r');
                pStream.WriteByte((byte)'y');
                pStream.WriteByte((byte)'p');
                pStream.WriteByte((byte)'t');
                pStream.WriteByte(FType); // Verzia
                byte[] B1 = BitConverter.GetBytes(OriginalSize);
                pStream.Write(B1, 0, B1.Length);
                byte[] B2 = System.Text.Encoding.Default.GetBytes(OriginalName);
                byte Len = B2.Length > 255 ? (byte)255 : (byte)B2.Length;
                pStream.WriteByte(Len); // Dlzka nazvu
                pStream.Write(B2, 0, Len); // Zapis nazvu
            }
            catch
            {
            }
        }
        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public virtual void Init(byte[] pPassword, System.IO.Stream pStream)
        {
            PreparePassword(pPassword); // Pripravim heslo
            try
            {
                pStream.WriteByte((byte)'t'); // Signatura
                pStream.WriteByte((byte)'l');
                pStream.WriteByte((byte)'m');
                pStream.WriteByte((byte)'e');
                pStream.WriteByte((byte)'n');
                pStream.WriteByte((byte)'c');
                pStream.WriteByte((byte)'r');
                pStream.WriteByte((byte)'y');
                pStream.WriteByte((byte)'p');
                pStream.WriteByte((byte)'t');
                pStream.WriteByte(FType); // Verzia
                byte[] B1 = BitConverter.GetBytes(OriginalSize);
                pStream.Write(B1, 0, B1.Length);
                byte[] B2 = System.Text.Encoding.Default.GetBytes(OriginalName);
                byte Len = B2.Length > 255 ? (byte)255 : (byte)B2.Length;
                pStream.WriteByte(Len); // Dlzka nazvu
                pStream.Write(B2, 0, Len); // Zapis nazvu
            }
            catch
            {
            }
        }
        /// <summary>Uzatvorenie sifrovania</summary>
        public virtual void Close()
        {
        }
        /// <summary>Zapis dat</summary>
        /// <param name="pBuffer">buffer</param>
        /// <param name="pLength">dlzka</param>
        /// <returns>0 alebo kod chyby</returns>
        public virtual int WriteData(byte[] pBuffer, int pLength)
        {
            return 0; // OK
        }

        /// <summary>Vytvorenie objektu sifrovania</summary>
        /// <param name="pType">typ</param>
        /// <returns></returns>
        public static IEncryptor CreateEncryptor(int pType)
        {
            switch (pType)
            {
                case ENCRYPTION_TYPE_AES128: return new IEncryptor_AES(ENCRYPTION_TYPE_AES128);
                case ENCRYPTION_TYPE_AES192: return new IEncryptor_AES(ENCRYPTION_TYPE_AES192);
                case ENCRYPTION_TYPE_AES256: return new IEncryptor_AES(ENCRYPTION_TYPE_AES256);
                case ENCRYPTION_TYPE_DES: return new IEncryptor_DES();
                case ENCRYPTION_TYPE_RC2_64: return new IEncryptor_RC2(ENCRYPTION_TYPE_RC2_64);
                case ENCRYPTION_TYPE_RC2_128: return new IEncryptor_RC2(ENCRYPTION_TYPE_RC2_128);
                case ENCRYPTION_TYPE_TRIPLE_DES_128: return new IEncryptor_TRIPLE_DES(ENCRYPTION_TYPE_TRIPLE_DES_128);
                case ENCRYPTION_TYPE_TRIPLE_DES_192: return new IEncryptor_TRIPLE_DES(ENCRYPTION_TYPE_TRIPLE_DES_192);
                default: return null;
            }
        }
        /// <summary>Ziskanie informacii o sifrovani</summary>
        /// <param name="pFileName">nazov suboru</param>
        /// <param name="pType">typ pouziteho sifrovania</param>
        /// <param name="pSize">velkost</param>
        /// <param name="pOriginalFileName">originalny nazov</param>
        /// <returns>true / false</returns>
        public static bool GetEncryptionInfo(string pFileName, out int pType, out long pSize, out string pOriginalFileName)
        {
            pType = -1; pSize = -1; pOriginalFileName = "";
            try
            {
                using (System.IO.BinaryReader R = new System.IO.BinaryReader(new System.IO.FileStream(pFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read)))
                {
                    if ((char)R.ReadByte() != 't') return false;
                    if ((char)R.ReadByte() != 'l') return false;
                    if ((char)R.ReadByte() != 'm') return false;
                    if ((char)R.ReadByte() != 'e') return false;
                    if ((char)R.ReadByte() != 'n') return false;
                    if ((char)R.ReadByte() != 'c') return false;
                    if ((char)R.ReadByte() != 'r') return false;
                    if ((char)R.ReadByte() != 'y') return false;
                    if ((char)R.ReadByte() != 'p') return false;
                    if ((char)R.ReadByte() != 't') return false;
                    pType = (int)R.ReadByte(); // Typ
                    byte[] B1 = R.ReadBytes(8); // Dlzka suboru
                    pSize = BitConverter.ToInt64(B1, 0);
                    int L = (int)R.ReadByte(); // Dlzka nazvu
                    if (L > 0)
                    {
                        B1 = R.ReadBytes(L); // Nacitam pole
                        pOriginalFileName = System.Text.Encoding.Default.GetString(B1);
                    }
                }

                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>Generovanie suboru s heslom</summary>
        /// <param name="pFileName">nazov suboru</param>
        /// <returns>true / false</returns>
        public static bool GeneratePasswordFile(string pFileName)
        {
            try
            {
                byte[] Data = new byte[512];
                Random Rnd = new Random();
                Rnd.NextBytes(Data); // Vyplnim nahodnymi bajtmi
                
                byte[] ID = BitConverter.GetBytes(IApp.App.InstalledInstanceID); // Prezeniem cez to este aj ID instancie
                for (int i = 0, j = 0; i < Data.Length; i++)
                {
                    Data[i] ^= ID[j++];
                    if (j >= ID.Length) j = 0; // Pretieklo?
                }
                System.IO.File.WriteAllBytes(pFileName, Data); // Zapisem do suboru
                return true; // Vsetko OK
            }
            catch
            {
                return false; // Chyba
            }
        }
        /// <summary>Kontrola validity suboru s heslom</summary>
        /// <param name="pFileName">nazov suboru</param>
        /// <returns>true / false</returns>
        public static bool IsValidPWDFile(string pFileName)
        {
            try
            {
                return new System.IO.FileInfo(pFileName).Length == 512;
            }
            catch
            {
                return false; // Chyba
            }
        }
    }

    /// <summary>Trieda IEncryptor_AES</summary>
    public class IEncryptor_AES : IEncryptor
    {
        protected System.Security.Cryptography.RijndaelManaged FAlg;
        protected System.Security.Cryptography.CryptoStream FCryptStream;
        protected System.IO.Compression.GZipStream FStream;
        protected long FWritedBytes;

        /// <summary>Konstruktor</summary>
        public IEncryptor_AES(int pType)
        {
            FAlg = new System.Security.Cryptography.RijndaelManaged();
            FAlg.Mode = System.Security.Cryptography.CipherMode.CBC;
            FAlg.BlockSize = 128;
            FAlg.FeedbackSize = 128;
            FAlg.Padding = System.Security.Cryptography.PaddingMode.ISO10126;

            switch (pType)
            {
                case ENCRYPTION_TYPE_AES128:
                    {
                        FType = ENCRYPTION_TYPE_AES128;
                        FAlg.KeySize = 128;
                    } break;
                case ENCRYPTION_TYPE_AES192:
                    {
                        FType = ENCRYPTION_TYPE_AES192;
                        FAlg.KeySize = 192;
                    } break;
                default:
                    {
                        FType = ENCRYPTION_TYPE_AES256;
                        FAlg.KeySize = 256;
                    } break;
            }
        }
        /// <summary>Dispose metoda</summary>
        public override void Dispose()
        {
            Close();
            FAlg = (System.Security.Cryptography.RijndaelManaged)ICore.DisposeObject(FAlg);
            base.Dispose(); // Volam predchodcu
        }

        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(string pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Compress, true);
                FWritedBytes = 0;
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(byte[] pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Compress, true);
                FWritedBytes = 0;
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Uzatvorenie sifrovania</summary>
        public override void Close()
        {
            if (FStream != null)
            {
                FStream.Flush();
                FStream.Close();
                FStream.Dispose();
                FStream = null;
                FCryptStream.Close();
            }
            FCryptStream = (System.Security.Cryptography.CryptoStream)ICore.DisposeObject(FStream);
        }
        /// <summary>Zapis dat</summary>
        /// <param name="pBuffer">buffer</param>
        /// <param name="pLength">dlzka</param>
        /// <returns>0 alebo kod chyby</returns>
        public override int WriteData(byte[] pBuffer, int pLength)
        {
            if (FStream == null) return -1; // Ziaden stream?
            try
            {
                FStream.Write(pBuffer, 0, pLength);
                FWritedBytes += pLength;
                return 0; // OK
            }
            catch
            {
                return -1; // Chyba
            }
        }
    }

    /// <summary>Trieda IEncryptor_DES</summary>
    public class IEncryptor_DES : IEncryptor
    {
        protected System.Security.Cryptography.DESCryptoServiceProvider FAlg;
        protected System.Security.Cryptography.CryptoStream FCryptStream;
        protected System.IO.Compression.GZipStream FStream;
        protected long FWritedBytes;

        /// <summary>Konstruktor</summary>
        public IEncryptor_DES()
        {
            FAlg = new System.Security.Cryptography.DESCryptoServiceProvider();
            FType = ENCRYPTION_TYPE_DES;
            FAlg.KeySize = 64;
        }
        /// <summary>Dispose metoda</summary>
        public override void Dispose()
        {
            Close();
            FAlg = (System.Security.Cryptography.DESCryptoServiceProvider)ICore.DisposeObject(FAlg);
            base.Dispose(); // Volam predchodcu
        }

        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(string pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Compress, true);
                FWritedBytes = 0;
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(byte[] pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Compress, true);
                FWritedBytes = 0;
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Uzatvorenie sifrovania</summary>
        public override void Close()
        {
            if (FStream != null)
            {
                FStream.Flush();
                FStream.Close();
                FStream.Dispose();
                FStream = null;
                FCryptStream.Close();
            }
            FCryptStream = (System.Security.Cryptography.CryptoStream)ICore.DisposeObject(FStream);
        }
        /// <summary>Zapis dat</summary>
        /// <param name="pBuffer">buffer</param>
        /// <param name="pLength">dlzka</param>
        /// <returns>0 alebo kod chyby</returns>
        public override int WriteData(byte[] pBuffer, int pLength)
        {
            if (FStream == null) return -1; // Ziaden stream?
            try
            {
                FStream.Write(pBuffer, 0, pLength);
                FWritedBytes += pLength;
                return 0; // OK
            }
            catch
            {
                return -1; // Chyba
            }
        }
    }

    /// <summary>Trieda IEncryptor_RC2</summary>
    public class IEncryptor_RC2 : IEncryptor
    {
        protected System.Security.Cryptography.RC2CryptoServiceProvider FAlg;
        protected System.Security.Cryptography.CryptoStream FCryptStream;
        protected System.IO.Compression.GZipStream FStream;
        protected long FWritedBytes;

        /// <summary>Konstruktor</summary>
        public IEncryptor_RC2(int pType)
        {
            FAlg = new System.Security.Cryptography.RC2CryptoServiceProvider();
            switch (pType)
            {
                case ENCRYPTION_TYPE_RC2_64:
                    {
                        FType = ENCRYPTION_TYPE_RC2_64;
                        FAlg.KeySize = 64;
                    } break;
                default:
                    {
                        FType = ENCRYPTION_TYPE_RC2_128;
                        FAlg.KeySize = 128;
                    } break;
            }
        }
        /// <summary>Dispose metoda</summary>
        public override void Dispose()
        {
            Close();
            FAlg = (System.Security.Cryptography.RC2CryptoServiceProvider)ICore.DisposeObject(FAlg);
            base.Dispose(); // Volam predchodcu
        }

        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(string pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Compress, true);
                FWritedBytes = 0;
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(byte[] pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Compress, true);
                FWritedBytes = 0;
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Uzatvorenie sifrovania</summary>
        public override void Close()
        {
            if (FStream != null)
            {
                FStream.Flush();
                FStream.Close();
                FStream.Dispose();
                FStream = null;
                FCryptStream.Close();
            }
            FCryptStream = (System.Security.Cryptography.CryptoStream)ICore.DisposeObject(FStream);
        }
        /// <summary>Zapis dat</summary>
        /// <param name="pBuffer">buffer</param>
        /// <param name="pLength">dlzka</param>
        /// <returns>0 alebo kod chyby</returns>
        public override int WriteData(byte[] pBuffer, int pLength)
        {
            if (FStream == null) return -1; // Ziaden stream?
            try
            {
                FStream.Write(pBuffer, 0, pLength);
                FWritedBytes += pLength;
                return 0; // OK
            }
            catch
            {
                return -1; // Chyba
            }
        }
    }

    /// <summary>Trieda IEncryptor_TRIPLE_DES</summary>
    public class IEncryptor_TRIPLE_DES : IEncryptor
    {
        protected System.Security.Cryptography.TripleDESCryptoServiceProvider FAlg;
        protected System.Security.Cryptography.CryptoStream FCryptStream;
        protected System.IO.Compression.GZipStream FStream;
        protected long FWritedBytes;

        /// <summary>Konstruktor</summary>
        public IEncryptor_TRIPLE_DES(int pType)
        {
            FAlg = new System.Security.Cryptography.TripleDESCryptoServiceProvider();
            switch (pType)
            {
                case ENCRYPTION_TYPE_TRIPLE_DES_128:
                    {
                        FType = ENCRYPTION_TYPE_TRIPLE_DES_128;
                        FAlg.KeySize = 128;
                    } break;
                default:
                    {
                        FType = ENCRYPTION_TYPE_TRIPLE_DES_192;
                        FAlg.KeySize = 192;
                    } break;
            }
        }
        /// <summary>Dispose metoda</summary>
        public override void Dispose()
        {
            Close();
            FAlg = (System.Security.Cryptography.TripleDESCryptoServiceProvider)ICore.DisposeObject(FAlg);
            base.Dispose(); // Volam predchodcu
        }

        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(string pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Compress, true);
                FWritedBytes = 0;
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(byte[] pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Compress, true);
                FWritedBytes = 0;
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Uzatvorenie sifrovania</summary>
        public override void Close()
        {
            if (FStream != null)
            {
                FStream.Flush();
                FStream.Close();
                FStream.Dispose();
                FStream = null;
                FCryptStream.Close();
            }
            FCryptStream = (System.Security.Cryptography.CryptoStream)ICore.DisposeObject(FStream);
        }
        /// <summary>Zapis dat</summary>
        /// <param name="pBuffer">buffer</param>
        /// <param name="pLength">dlzka</param>
        /// <returns>0 alebo kod chyby</returns>
        public override int WriteData(byte[] pBuffer, int pLength)
        {
            if (FStream == null) return -1; // Ziaden stream?
            try
            {
                FStream.Write(pBuffer, 0, pLength);
                FWritedBytes += pLength;
                return 0; // OK
            }
            catch
            {
                return -1; // Chyba
            }
        }
    }


    /// <summary>Trieda IDecryptor</summary>
    public class IDecryptor : IDisposable
    {
        protected System.Security.Cryptography.PasswordDeriveBytes FPassword; // Heslo

        public long OriginalSize;
        public string OriginalName;
        public int Type;

        /// <summary>Konstruktor</summary>
        public IDecryptor()
        {
            FPassword = null;
            Type = -1;
            OriginalName = "";
            OriginalSize = -1;
        }
        /// <summary>Dispose metoda</summary>
        public virtual void Dispose()
        {
            FPassword = (System.Security.Cryptography.PasswordDeriveBytes)ICore.DisposeObject(FPassword);
        }

        /// <summary>Priprava hesla</summary>
        /// <param name="pValue">heslo</param>
        protected void PreparePassword(string pValue)
        {
            FPassword = new System.Security.Cryptography.PasswordDeriveBytes(pValue, new byte[] { 0x22, 0x31, 0x45, 0x51, 0x64, 0x7a, 0x87, 0x96, 0xa0, 0xbb, 0xce, 0xd8, 0xe5 });
        }
        /// <summary>Priprava hesla</summary>
        /// <param name="pValue">heslo</param>
        protected void PreparePassword(byte[] pValue)
        {
            try
            {
                FPassword = new System.Security.Cryptography.PasswordDeriveBytes(System.Convert.ToBase64String(pValue), new byte[] { 0x22, 0x31, 0x45, 0x51, 0x64, 0x7a, 0x87, 0x96, 0xa0, 0xbb, 0xce, 0xd8, 0xe5 });
            }
            catch
            {
            }
        }

        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public virtual void Init(string pPassword, System.IO.Stream pStream)
        {
            PreparePassword(pPassword); // Pripravim heslo
        }
        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public virtual void Init(byte[] pPassword, System.IO.Stream pStream)
        {
            PreparePassword(pPassword); // Pripravim heslo
        }
        /// <summary>Uzatvorenie sifrovania</summary>
        public virtual void Close()
        {
        }
        /// <summary>Nacitanie dat</summary>
        /// <param name="pBuffer">buffer</param>
        /// <param name="pMaxLength">dlzka</param>
        /// <returns>pocet nacitanych bajtov alebo kod chyby</returns>
        public virtual int ReadData(byte[] pBuffer, int pMaxLength)
        {
            return 0;
        }

        /// <summary>Otvorenie decryptora</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        /// <param name="ErrorCode">kod chyby</param>
        /// <returns>objekt decryptora</returns>
        public static IDecryptor OpenDecryptor(System.IO.Stream pStream, out int ErrorCode)
        {
            ErrorCode = 1;
            try
            {
                if ((char)pStream.ReadByte() != 't') return null;
                if ((char)pStream.ReadByte() != 'l') return null;
                if ((char)pStream.ReadByte() != 'm') return null;
                if ((char)pStream.ReadByte() != 'e') return null;
                if ((char)pStream.ReadByte() != 'n') return null;
                if ((char)pStream.ReadByte() != 'c') return null;
                if ((char)pStream.ReadByte() != 'r') return null;
                if ((char)pStream.ReadByte() != 'y') return null;
                if ((char)pStream.ReadByte() != 'p') return null;
                if ((char)pStream.ReadByte() != 't') return null;
                int Type = (int)pStream.ReadByte(); // Typ
                byte[] B1 = new byte[8];
                if (pStream.Read(B1, 0, 8) != 8) return null; // Dlzka suboru
                long OriginalSize = BitConverter.ToInt64(B1, 0);
                int L = (int)pStream.ReadByte(); // Dlzka nazvu

                string OriginalName = "";
                if (L > 0)
                {
                    B1 = new byte[L];
                    if (pStream.Read(B1, 0, L) != L) return null; // Nacitam pole
                    OriginalName = System.Text.Encoding.Default.GetString(B1);
                }

                // Nacitane a vytvorim objekt

                IDecryptor D = null;
                switch (Type)
                {
                    case IEncryptor.ENCRYPTION_TYPE_AES128: D = new IDecryptor_AES(IEncryptor.ENCRYPTION_TYPE_AES128); break;
                    case IEncryptor.ENCRYPTION_TYPE_AES192: D = new IDecryptor_AES(IEncryptor.ENCRYPTION_TYPE_AES192); break;
                    case IEncryptor.ENCRYPTION_TYPE_AES256: D = new IDecryptor_AES(IEncryptor.ENCRYPTION_TYPE_AES256); break;
                    case IEncryptor.ENCRYPTION_TYPE_DES: D = new IDecryptor_DES(); break;
                    case IEncryptor.ENCRYPTION_TYPE_RC2_64: D = new IDecryptor_RC2(IEncryptor.ENCRYPTION_TYPE_RC2_64); break;
                    case IEncryptor.ENCRYPTION_TYPE_RC2_128: D = new IDecryptor_RC2(IEncryptor.ENCRYPTION_TYPE_RC2_128); break;
                    case IEncryptor.ENCRYPTION_TYPE_TRIPLE_DES_128: D = new IDecryptor_TRIPLE_DES(IEncryptor.ENCRYPTION_TYPE_TRIPLE_DES_128); break;
                    case IEncryptor.ENCRYPTION_TYPE_TRIPLE_DES_192: D = new IDecryptor_TRIPLE_DES(IEncryptor.ENCRYPTION_TYPE_TRIPLE_DES_192); break;
                    default: return null; // Neznamy typ
                }

                D.OriginalName = OriginalName; D.OriginalSize = OriginalSize;
                ErrorCode = 0;
                return D;
            }
            catch
            {
                ErrorCode = -1;
                return null;
            }
        }
    }

    /// <summary>Trieda IDecryptor_AES</summary>
    public class IDecryptor_AES : IDecryptor
    {
        protected System.Security.Cryptography.RijndaelManaged FAlg;
        protected System.Security.Cryptography.CryptoStream FCryptStream;
        protected System.IO.Compression.GZipStream FStream;

        /// <summary>Konstruktor</summary>
        public IDecryptor_AES(int pType)
        {
            FStream = null;
            FAlg = new System.Security.Cryptography.RijndaelManaged();
            FAlg.Mode = System.Security.Cryptography.CipherMode.CBC;
            FAlg.BlockSize = 128;
            FAlg.FeedbackSize = 128;
            FAlg.Padding = System.Security.Cryptography.PaddingMode.ISO10126;

            switch (pType)
            {
                case IEncryptor.ENCRYPTION_TYPE_AES128:
                    {
                        FAlg.KeySize = 128;
                    } break;
                case IEncryptor.ENCRYPTION_TYPE_AES192:
                    {
                        FAlg.KeySize = 192;
                    } break;
                default:
                    {
                        FAlg.KeySize = 256;
                    } break;
            }
        }
        /// <summary>Dispose metoda</summary>
        public override void Dispose()
        {
            Close();
            FAlg = (System.Security.Cryptography.RijndaelManaged)ICore.DisposeObject(FAlg);
            base.Dispose(); // Volam predchodcu
        }

        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(string pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Decompress, true);
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(byte[] pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Decompress, true);
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Uzatvorenie sifrovania</summary>
        public override void Close()
        {
            try
            {
                if (FStream != null)
                {
                    FStream.Close();
                    FStream.Dispose();
                    FStream = null;
                }
                FCryptStream = (System.Security.Cryptography.CryptoStream)ICore.DisposeObject(FStream);
            }
            catch
            {
            }
        }
        /// <summary>Nacitanie dat</summary>
        /// <param name="pBuffer">buffer</param>
        /// <param name="pMaxLength">dlzka</param>
        /// <returns>pocet nacitanych bajtov alebo kod chyby</returns>
        public override int ReadData(byte[] pBuffer, int pMaxLength)
        {
            if (FStream == null) return -1; // Ziaden stream?
            try
            {
                return FStream.Read(pBuffer, 0, pMaxLength);
            }
            catch (System.Security.Cryptography.CryptographicException)
            {
                return -2; // Chyba desifrovania
            }
            catch
            {
                return -1; // Chyba
            }
        }
    }

    /// <summary>Trieda IDecryptor_DES</summary>
    public class IDecryptor_DES : IDecryptor
    {
        protected System.Security.Cryptography.DESCryptoServiceProvider FAlg;
        protected System.Security.Cryptography.CryptoStream FCryptStream;
        protected System.IO.Compression.GZipStream FStream;

        /// <summary>Konstruktor</summary>
        public IDecryptor_DES()
        {
            FStream = null;
            FAlg = new System.Security.Cryptography.DESCryptoServiceProvider();
            FAlg.KeySize = 64;
        }
        /// <summary>Dispose metoda</summary>
        public override void Dispose()
        {
            Close();
            FAlg = (System.Security.Cryptography.DESCryptoServiceProvider)ICore.DisposeObject(FAlg);
            base.Dispose(); // Volam predchodcu
        }

        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(string pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Decompress, true);
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(byte[] pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Decompress, true);
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Uzatvorenie sifrovania</summary>
        public override void Close()
        {
            try
            {
                if (FStream != null)
                {
                    FStream.Close();
                    FStream.Dispose();
                    FStream = null;
                }
                FCryptStream = (System.Security.Cryptography.CryptoStream)ICore.DisposeObject(FStream);
            }
            catch
            {
            }
        }
        /// <summary>Nacitanie dat</summary>
        /// <param name="pBuffer">buffer</param>
        /// <param name="pMaxLength">dlzka</param>
        /// <returns>pocet nacitanych bajtov alebo kod chyby</returns>
        public override int ReadData(byte[] pBuffer, int pMaxLength)
        {
            if (FStream == null) return -1; // Ziaden stream?
            try
            {
                return FStream.Read(pBuffer, 0, pMaxLength);
            }
            catch (System.Security.Cryptography.CryptographicException)
            {
                return -2; // Chyba desifrovania
            }
            catch
            {
                return -1; // Chyba
            }
        }
    }

    /// <summary>Trieda IDecryptor_RC2</summary>
    public class IDecryptor_RC2 : IDecryptor
    {
        protected System.Security.Cryptography.RC2CryptoServiceProvider FAlg;
        protected System.Security.Cryptography.CryptoStream FCryptStream;
        protected System.IO.Compression.GZipStream FStream;

        /// <summary>Konstruktor</summary>
        public IDecryptor_RC2(int pType)
        {
            FStream = null;
            FAlg = new System.Security.Cryptography.RC2CryptoServiceProvider();
            switch (pType)
            {
                case IEncryptor.ENCRYPTION_TYPE_RC2_64:
                    {
                        FAlg.KeySize = 64;
                    } break;
                default:
                    {
                        FAlg.KeySize = 128;
                    } break;
            }
        }
        /// <summary>Dispose metoda</summary>
        public override void Dispose()
        {
            Close();
            FAlg = (System.Security.Cryptography.RC2CryptoServiceProvider)ICore.DisposeObject(FAlg);
            base.Dispose(); // Volam predchodcu
        }

        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(string pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Decompress, true);
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(byte[] pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Decompress, true);
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Uzatvorenie sifrovania</summary>
        public override void Close()
        {
            try
            {
                if (FStream != null)
                {
                    FStream.Close();
                    FStream.Dispose();
                    FStream = null;
                }
                FCryptStream = (System.Security.Cryptography.CryptoStream)ICore.DisposeObject(FStream);
            }
            catch
            {
            }
        }
        /// <summary>Nacitanie dat</summary>
        /// <param name="pBuffer">buffer</param>
        /// <param name="pMaxLength">dlzka</param>
        /// <returns>pocet nacitanych bajtov alebo kod chyby</returns>
        public override int ReadData(byte[] pBuffer, int pMaxLength)
        {
            if (FStream == null) return -1; // Ziaden stream?
            try
            {
                return FStream.Read(pBuffer, 0, pMaxLength);
            }
            catch (System.Security.Cryptography.CryptographicException)
            {
                return -2; // Chyba desifrovania
            }
            catch
            {
                return -1; // Chyba
            }
        }
    }

    /// <summary>Trieda IDecryptor_TRIPLE_DES</summary>
    public class IDecryptor_TRIPLE_DES : IDecryptor
    {
        protected System.Security.Cryptography.TripleDESCryptoServiceProvider FAlg;
        protected System.Security.Cryptography.CryptoStream FCryptStream;
        protected System.IO.Compression.GZipStream FStream;

        /// <summary>Konstruktor</summary>
        public IDecryptor_TRIPLE_DES(int pType)
        {
            FStream = null;
            FAlg = new System.Security.Cryptography.TripleDESCryptoServiceProvider();
            switch (pType)
            {
                case IEncryptor.ENCRYPTION_TYPE_TRIPLE_DES_128:
                    {
                        FAlg.KeySize = 128;
                    } break;
                default:
                    {
                        FAlg.KeySize = 192;
                    } break;
            }
        }
        /// <summary>Dispose metoda</summary>
        public override void Dispose()
        {
            Close();
            FAlg = (System.Security.Cryptography.TripleDESCryptoServiceProvider)ICore.DisposeObject(FAlg);
            base.Dispose(); // Volam predchodcu
        }

        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(string pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Decompress, true);
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Inicializacia</summary>
        /// <param name="pPassword">heslo</param>
        /// <param name="pStream">stream</param>
        public override void Init(byte[] pPassword, System.IO.Stream pStream)
        {
            base.Init(pPassword, pStream); // Volam predchodcu
            try
            {
                FAlg.Key = FPassword.GetBytes(FAlg.Key.Length); FAlg.IV = FPassword.GetBytes(FAlg.IV.Length);
                FCryptStream = new System.Security.Cryptography.CryptoStream(pStream, FAlg.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read);
                FStream = new System.IO.Compression.GZipStream(FCryptStream, System.IO.Compression.CompressionMode.Decompress, true);
            }
            catch
            {
                FStream = null;
            }
        }
        /// <summary>Uzatvorenie sifrovania</summary>
        public override void Close()
        {
            try
            {
                if (FStream != null)
                {
                    FStream.Close();
                    FStream.Dispose();
                    FStream = null;
                }
                FCryptStream = (System.Security.Cryptography.CryptoStream)ICore.DisposeObject(FStream);
            }
            catch
            {
            }
        }
        /// <summary>Nacitanie dat</summary>
        /// <param name="pBuffer">buffer</param>
        /// <param name="pMaxLength">dlzka</param>
        /// <returns>pocet nacitanych bajtov alebo kod chyby</returns>
        public override int ReadData(byte[] pBuffer, int pMaxLength)
        {
            if (FStream == null) return -1; // Ziaden stream?
            try
            {
                return FStream.Read(pBuffer, 0, pMaxLength);
            }
            catch (System.Security.Cryptography.CryptographicException)
            {
                return -2; // Chyba desifrovania
            }
            catch
            {
                return -1; // Chyba
            }
        }
    }
}
